#pragma once

#include<iostream>
#include<sys/epoll.h>
#include<cstring>
#include<cerrno>
#include"Log.hpp"

using namespace std;

class Epoller
{
public:

    static const int size = 128;

    Epoller()
    {
        //创建epoll模型
        _epfd = epoll_create(size);
        if(_epfd < 0)
        {
            lg(Error, "epoll create error, errorstring: %s", strerror(errno));
            exit(1);
        }

        lg(Info, "epoll create success:%d", _epfd);
    }

    int EpollerWait(struct epoll_event revents[], int num)
    {
        int n = epoll_wait(_epfd, revents, num, _timeout);//这里的_timeout可以设置等待方式, 阻塞等待还是非阻塞都可以实现

        return n;
    }

    //对Epoll模型进行增删查改等操作
    int EpollerUpdate(int oper, int sock, uint32_t event)
    {
        if(oper == EPOLL_CTL_DEL)
        {
            int n = epoll_ctl(_epfd, oper, sock, nullptr);//删除最后一个参数可以设置成为nullptr
            if(n < 0)
            {
                lg(Error, "delete epoll error!");
            }
        }   
        else
        {
            struct epoll_event ev;
            ev.events = event;
            ev.data.fd = sock;

            //通过系统调用向红黑树中新增节点, 让我们的节点和底层回调函数产生联系
            int n = epoll_ctl(_epfd, oper, sock, &ev);
            if(n != 0)
            {
                lg(Error, "epoll ctl error!");
            }
        }
    }

    ~Epoller()
    {
        if(_epfd > 0)
        {
            close(_epfd);
        }
    }

private:
    Epoller(const Epoller& ep) = delete;
    const Epoller& operator=(const Epoller& ep) = delete;

private:
    int _epfd;
    int _timeout{3000};
};
